/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.web.controller;

import com.google.common.collect.Lists;
import com.intelligent.ispc.common.dto.JsonPageResponseDto;
import com.intelligent.ispc.common.dto.JsonResponseDto;
import com.intelligent.ispc.common.mapper.JsonMapper;
import com.intelligent.ispc.common.utils.ApplicationException;
import com.intelligent.ispc.common.utils.ExceptionMessages;
import com.intelligent.ispc.common.web.ProcessEvent;
import com.intelligent.ispc.common.web.ProcessInfo;
import com.intelligent.ispc.common.web.Servlets;
import com.intelligent.ispc.core.dto.ToleranceItemDto;
import com.intelligent.ispc.core.dto.ToleranceSchemeDto;
import com.intelligent.ispc.core.service.SecurityService;
import com.intelligent.ispc.core.service.ToleranceService;
import com.intelligent.ispc.common.mapper.BeanMapper;
import com.intelligent.ispc.common.utils.ExceptionMessages;
import com.intelligent.ispc.core.dto.*;
import com.intelligent.ispc.core.service.ToleranceService;
import com.intelligent.ispc.external.rcall.dto.NormalDistributionDto;
import com.intelligent.ispc.utils.Constant;
import com.intelligent.ispc.web.utils.ApplicationUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletRequest;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.util.*;

/**
 * Created by Ethan.Yang on 2016/8/19.
 */
@Controller
@RequestMapping(value = "/analysis/tolerance")
public class ToleranceController {

    @Autowired
    private ToleranceService toleranceService;

    @Autowired
    private SecurityService securityService;

    @Autowired
    private SimpMessagingTemplate msgTemplate;

    private long fileSize;
    private long readSize;

    @RequestMapping(value = "", method = RequestMethod.GET)
    public String main(Model model) {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:view")) {
            return "error/noPermission";
        }
        return "analysis/tolerance/toleranceAnalysis";
    }

    @ResponseBody
    @RequestMapping(value = "/dc")
    public JsonResponseDto Scheme(Long projectId, Model model) {
        List<ToleranceSchemeDto> list = new ArrayList<ToleranceSchemeDto>();
        try {
            list = toleranceService.findSchemeByProject(projectId);
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }

        return JsonResponseDto.SUCCESS().setBody(list);
    }

    @ResponseBody
    @RequestMapping(value = "/toleranceAnalysis")
    public JsonResponseDto searchToleranceItem(ToleranceSearchConditionDto conditionDto, Model model) {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:view")) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
        }
        ToleranceResultDto dto = null;
        try {
            dto = toleranceService.analysis(conditionDto);
        } catch (Exception e) {
            e.printStackTrace();
            return JsonResponseDto.FAILURE().setMessage(e.getMessage());
        }

        return JsonResponseDto.SUCCESS().setBody(dto);
    }

    @ResponseBody
    @RequestMapping(value = "/checkToleranceName")
    public JsonResponseDto checkToleranceName(ServletRequest request, Model model) {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:view")) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
        }

        Long projectId = Long.valueOf(request.getParameter("project"));
        String schemeName = String.valueOf(request.getParameter("dc"));
        boolean isExist = false;
        try {
            isExist = toleranceService.isSchemeExistInProject(projectId, schemeName);
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }

        return JsonResponseDto.SUCCESS().setBody(!isExist);
    }

    @ResponseBody
    @RequestMapping(value = "/getItem")
    public JsonPageResponseDto findItems(ServletRequest request, Model model) {

        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:view")) {
            return JsonPageResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
        }
        List<ToleranceItemDto> items;
        try {
            Long schemeId = Long.valueOf(request.getParameter("search_dcIds"));
            items = toleranceService.findItemByScheme(schemeId);
        } catch (ApplicationException ex) {
            return JsonPageResponseDto.FAILURE().setMessage(ex.getMessage());
        }
        return JsonPageResponseDto.SUCCESS().setBody(items);
    }

    @ResponseBody
    @RequestMapping(value = "/createDC", method = RequestMethod.POST)
    public JsonResponseDto createDimensionChain(@RequestBody ToleranceSchemeDto toleranceSchemeDto) {

        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:view")) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
        }
        try {
            Long projectId = toleranceSchemeDto.getProjectId();
            String name = toleranceSchemeDto.getName();
            boolean flag = toleranceService.isSchemeExistInProject(projectId, name);
            if (!flag) {
                toleranceService.createScheme(toleranceSchemeDto);
            } else {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_OBJECT_ALREADY_EXISTS);
            }
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
        return JsonResponseDto.SUCCESS();
    }

    @ResponseBody
    @RequestMapping(value = "/addItem", method = RequestMethod.POST)
    public JsonResponseDto addToleranceItem(@RequestBody ToleranceItemDto toleranceItemDto) {

        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:view")) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
        }
        try {
            toleranceService.createItem(toleranceItemDto);
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
        return JsonResponseDto.SUCCESS();
    }

    @ResponseBody
    @RequestMapping(value = "/deleteItem")
    public JsonResponseDto deleteItem(ServletRequest request) {

        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:delete")) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
        }
        try {
            Long id = Long.valueOf(request.getParameter("id"));
            toleranceService.deleteItem(id);
        } catch (Exception e) {
            return JsonResponseDto.FAILURE().setMessage(e.getMessage());
        }
        return JsonResponseDto.SUCCESS();
    }

    @ResponseBody
    @RequestMapping(value = "/updateItem", method = RequestMethod.POST)
    public JsonResponseDto updateItem(@RequestBody ToleranceItemDto toleranceItemDto) {

        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:edit")) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
        }
        try {
            toleranceService.updateItem(toleranceItemDto);
        } catch (ApplicationException ex) {
            ex.printStackTrace();
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
        return JsonResponseDto.SUCCESS();
    }

    @ResponseBody
    @RequestMapping(value = "/result")
    public JsonResponseDto exportToleranceResult(ToleranceSearchConditionDto conditionDto, Model model) {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:view")) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
        }
        try {
            toleranceService.export(conditionDto);
        } catch (ApplicationException e) {
            return JsonResponseDto.FAILURE().setMessage(e.getMessage());
        }
        return JsonResponseDto.SUCCESS();
    }

    @RequestMapping(value = "/import", method = RequestMethod.POST)
    public ModelAndView dataImport(HttpServletRequest request, HttpServletResponse response) {

        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("analysis:tolerance:import")) {
            return new ModelAndView("error/noPermission");
        }

        ModelAndView mv = new ModelAndView();
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (!isMultipart) {
            return mv;
        }
        Map<Double, Double> mapProcess = new HashMap<Double, Double>();

        final HttpSession session = request.getSession();
        try {
            FileItemFactory factory = new DiskFileItemFactory();
            Long userId = securityService.getCurrentUser().getId();
            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setProgressListener(new ProgressListener() {
                public void update(long pBytesRead, long pContentLength, int pItems) {
                    fileSize = pContentLength;
                }
            });
            List<FileItem> items = upload.parseRequest(request);
            StringBuffer buffer = new StringBuffer();

            String dirPath = buffer.append(File.separator)
                    .append(ApplicationUtil.getProjectPathSeparator())
                    .append("upload")
                    .append(File.separator).toString();

            List<BaseDto> filePaths = Lists.newArrayList();
            String projectId = "";
            String toleranceName= null;
            String soltkey = null;
            String filePath = null;
            String fName = null;
            for (FileItem item : items) {
                if (item.isFormField()) {
                    if (item.getFieldName().equalsIgnoreCase("projectId")) {
                        projectId = item.getString();
                    }
                    if (item.getFieldName().equalsIgnoreCase("dcId")) {
                        toleranceName = item.getString();
                    }
                    if (item.getFieldName().equalsIgnoreCase("soltkey")) {
                        soltkey = item.getString();
                    }
                } else {

                    fName = new Date().getTime() + "_" + item.getName();
                    filePath = dirPath + fName;
                    File uploadFile = new File(filePath);
                    if (!uploadFile.exists()) {
                        uploadFile.createNewFile();
                    }
                    item.write(uploadFile);
                }
            }

            ToleranceSchemeDto toleranceSchemeDto = new ToleranceSchemeDto();

            String fileType =fName.substring(fName.lastIndexOf('.') + 1);
            toleranceSchemeDto.setName(toleranceName);
            toleranceSchemeDto.setProjectId(Long.valueOf(projectId));
            if(toleranceService.isSchemeExistInProject(Long.valueOf(projectId),toleranceName)){
                return mv;
            }
            ProcessEvent processEvent = getProcessEvent(userId, Long.valueOf(soltkey));
            if (fileType.equals("xls") || fileType.equals("xlsx")) {
                toleranceService.importScheme(toleranceSchemeDto, filePath, processEvent);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mv;
    }

    private ProcessEvent getProcessEvent(Long userId, Long soltkey) {
        return new ProcessEvent() {
            @Override
            public void update(double rate, String log, long rowReadSize, boolean isLastUpdate) {
                ProcessInfo pri = new ProcessInfo();
                pri.setRate(rate);
                pri.setLog(pri.getLog() + log);
                pri.setLastUpdate(isLastUpdate);
                pri.setReadSize(rowReadSize);
                pri.setTotalSize(fileSize);
                sendListenerResponse(pri, userId, soltkey);
            }
        };

    }

    private void sendListenerResponse(ProcessInfo response, Long userId, Long soltkey) {
        if (response == null) {
            throw new ApplicationException(ExceptionMessages.EXCEPTION_PARAMETER_INPUT_INVALID);
        }
        response.setTarget(Constant.UPLOAD_TARGET_GRR);
        JsonMapper mapper = new JsonMapper();
        String json = mapper.toJson(response);

        msgTemplate.setUserDestinationPrefix("/data/");
        msgTemplate.convertAndSend("/topic/data/importListener#" + soltkey + "#" + userId, json);
    }
}
